package com.hongyun.tms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.hongyun.tms.common.PageResponseDto;
import com.hongyun.tms.common.constants.DefaultCreateByConstant;
import com.hongyun.tms.common.constants.PordWorkConstant;
import com.hongyun.tms.common.dto.pordwork.*;
import com.hongyun.tms.common.utils.AttachUtil;
import com.hongyun.tms.common.utils.DateUtils;
import com.hongyun.tms.common.utils.MapperingUtils;
import com.hongyun.tms.common.vo.PordWorkVO;
import com.hongyun.tms.domain.SysFileBusinessDomain;
import com.hongyun.tms.entity.MShip;
import com.hongyun.tms.entity.PordWork;
import com.hongyun.tms.entity.ProdPlan;
import com.hongyun.tms.entity.SysFileBusiness;
import com.hongyun.tms.mapper.PordWorkMapper;
import com.hongyun.tms.service.IMShipService;
import com.hongyun.tms.service.IPordWorkService;
import com.hongyun.tms.service.IProdPlanService;
import com.hongyun.tms.service.ISysFileBusinessService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 拖轮作业记录表 服务实现类
 * </p>
 *
 * @author liPeng
 * @since 2024-06-24
 */
@Service
public class PordWorkServiceImpl extends ServiceImpl<PordWorkMapper, PordWork> implements IPordWorkService {

    @Resource
    @Lazy
    private IProdPlanService planService;

    @Resource
    @Lazy
    private IMShipService shipService;

    @Resource
    private ISysFileBusinessService fileBusinessService;

    @Resource
    private AttachUtil attachUtil;

    /**
     * 普通的作业记录(不包含特殊作业记录)
     *
     * @param query params
     * @return page
     */
    @Override
    public PageResponseDto<PordWorkVO> pageList(PordWorkQueryDto query) {
        // 分页初始化
        Page<PordWork> page = new Page<>(query.getStartPage(), query.getPageSize());

        // 初始化查询条件
        LambdaQueryWrapper<PordWork> queryWrapper = new LambdaQueryWrapper<>();

        // 如果有planCode，则查询对应的planId列表
        List<Long> planIdList = Lists.newArrayList();
        if (StringUtils.isNotBlank(query.getPlanCode())) {
            List<ProdPlan> planList = planService.list(new LambdaQueryWrapper<ProdPlan>()
                    .like(ProdPlan::getPlanCode, query.getPlanCode()));
            planIdList = planList.stream().map(ProdPlan::getId).collect(Collectors.toList());
        }

        // 设置查询条件
        queryWrapper
                .eq(query.getPlanId() != null, PordWork::getPlanId, query.getPlanId())
                .eq(query.getTugId() != null, PordWork::getTugId, query.getTugId())
                .eq(query.getStatus() != null, PordWork::getStatus, query.getStatus())
                .eq(StringUtils.isNotBlank(query.getShipKindCode()), PordWork::getShipKindCode, query.getShipKindCode())
                .eq(StringUtils.isNotBlank(query.getPortAreaCode()), PordWork::getPortAreaCode, query.getPortAreaCode())
                .eq(query.getCustomerId() != null, PordWork::getCustomerId, query.getCustomerId())
                .like(StringUtils.isNotBlank(query.getShipName()), PordWork::getShipName, query.getShipName())
                .like(StringUtils.isNotBlank(query.getTugNo()), PordWork::getTugNo, query.getTugNo())
                .like(StringUtils.isNotBlank(query.getCustomerName()), PordWork::getCustomerName, query.getCustomerName())
                .in(StringUtils.isNotBlank(query.getPlanCode()), PordWork::getPlanId, CollectionUtils.isNotEmpty(planIdList) ? planIdList : Collections.singleton(-1))
                .isNotNull(PordWork::getPlanId)
                .orderByDesc(PordWork::getPlanId);

        // 执行分页查询
        baseMapper.selectPage(page, queryWrapper);

        return new PageResponseDto(page, PordWorkVO.class);
    }

    /**
     * 特殊作业记录列表
     *
     * @param query query
     * @return specialList
     */
    @Override
    public PageResponseDto<PordWorkVO> pageSpecialList(PordWorkSpecialQueryDto query) {
        // 分页初始化
        Page<PordWork> page = new Page<>(query.getStartPage(), query.getPageSize());

        // 调用 XML 中定义的分页查询方法
        Page<PordWork> resultPage = baseMapper.selectSpecialWorkPage(page, query, PordWorkConstant.APPROVED_STATUS, PordWorkConstant.FEE_STATUS);

        return new PageResponseDto(resultPage, PordWorkVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdatePordWork(PordWorkSaveReqDto dto) {
        PordWork work = MapperingUtils.copyProperties(dto, PordWork.class)
                .setUpdateTime(LocalDateTime.now())
                .setUpdateBy(DefaultCreateByConstant.userId)
                .setUpdateByName(DefaultCreateByConstant.userId.toString())
                .setWorkLocation(dto.getWorkLocation());
        if (StringUtils.isNotBlank(dto.getBeginTime())) {
            work.setBeginTime(DateUtils.str2LocalDateTime(dto.getBeginTime()));
            work.setEndTime(DateUtils.str2LocalDateTime(dto.getEndTime()));
            work.setWorkHours(DateUtils.calculateDurationInHours(DateUtils.str2LocalDateTime(dto.getBeginTime()), DateUtils.str2LocalDateTime(dto.getEndTime())));
        }
        if (dto.getId() == null) {
            MShip ship = shipService.getById(dto.getShipId());
            if (ship != null) {
                work.setShipKindCode(ship.getShipKindCode());
                work.setShipKindName(ship.getShipKindName());
            }
            work.setCreateBy(DefaultCreateByConstant.userId);
            work.setCreateByName(DefaultCreateByConstant.userId.toString());
            work.setCreateTime(LocalDateTime.now());
            save(work);
        } else {
            updateById(work);
        }

        fileBusinessService.remove(new LambdaQueryWrapper<SysFileBusiness>().eq(SysFileBusiness::getBusinessId, work.getId()));
        //append attach handle---when execute finishWork operate
        if (CollectionUtils.isNotEmpty(dto.getAttachList())) {
            List<String> attachList = dto.getAttachList();
            List<SysFileBusinessDomain> businessDomainList = SysFileBusinessDomain.packageBasicInfo(attachList, work.getId());
            List<SysFileBusiness> fileBusinessList = MapperingUtils.copyList(businessDomainList, SysFileBusiness.class);
            fileBusinessService.saveBatch(fileBusinessList);
        }
    }

    @Override
    public PordWorkVO detail(Long id) {
        PordWork head = getById(id);
        PordWorkVO vo = MapperingUtils.copyProperties(head, PordWorkVO.class);

        //设置附件
        List<PordWorkVO.Attach> attachList = attachUtil.getAttachList(
                vo.getId(), PordWorkVO.Attach.class
        );
        vo.setAttachList(attachList);
        return vo;
    }

    /**
     * 特殊作业记录-总计费
     *
     * @param query 查询
     * @return fee
     */
    @Override
    public String specialListTotalAmount(PordWorkSpecialQueryDto query) {
        // 计算符合条件的总金额
        BigDecimal totalAmount = baseMapper.sumSpecialWorkAmount(query, PordWorkConstant.APPROVED_STATUS, PordWorkConstant.FEE_STATUS);
        return totalAmount != null ? totalAmount.toString() : "0";
    }

    /**
     * 导出特殊作业记录
     *
     * @param query      查询
     * @param exportType 导出类型，1表示特殊作业记录，2表示特殊作业计费。两者只相差一个字段fee
     * @return list
     */
    @Override
    public List<?> exportSpecialList(PordWorkSpecialQueryDto query, int exportType) {
        long currentPage = 1;
        List<PordWorkVO> allRecords = Lists.newArrayList();

        while (true) {
            query.setStartPage(currentPage);
            PageResponseDto<PordWorkVO> page = this.pageSpecialList(query);
            List<PordWorkVO> records = page.getRecords();
            allRecords.addAll(records);

            if (records.size() < query.getPageSize()) {
                // 当前页的记录数小于 pageSize，说明已经是最后一页
                break;
            }
            currentPage++;
        }
        return exportType == 1 ? MapperingUtils.copyList(allRecords, SpecialWorkExportDto.class) : MapperingUtils.copyList(allRecords, SpecialWorkFeeExportDto.class);
    }
}
